package link;

import lpt.ErrorLpt;

public class ErrorLptAdapter extends ErrorLpt {

	private ValueRegister valReg = new ValueRegister();
	
	@Override
	/**
	 * Returns the current bits on the LPT-cable
	 * the significant bits are in the lower (rightmost) 
	 * 5 bits
	 * @return a byte containing the bits on the cable in the lower (rightmost) 5 bits
	 */
	public byte readLPT(){
		boolean stop = false;
		do{
			byte b = (byte) ((super.readLPT() >> 3) & 0x1F);
			stop = valReg.add(b);
		}while(!stop);
		byte ret = (byte) (valReg.value() ^ 0x10); //for some reason this bit always arrives flipped
		valReg.reset();
		return ret;
	}
	
	private class ValueRegister{

		/**
		 * an array of the read counts of all possible values, the byte values are the indexes here, the int's that make up the 
		 * array are the read counts
		 */
		private int[] vals = new int[32]; //LPT reads 5 bits max, thus the maximum value read is 32, and since all bits are
											//in the rightmost 5 bits, this value is always 0<=val<32
		/**
		 * an array of which values in the vals array actually contain data, could contain doubles.
		 * The values in the array are the indexes in the vals array which contain data
		 */
		private byte[] attempts = new byte[Constants.MAX_READ_TRYS];
		/**
		 * the next index to write to in the attempts array
		 */
		private int attemptN = 0;
		
		/**
		 * add a new read value to the register, this will keep track of the number of times this value is read
		 * @param val the value that is read
		 * @return if this value is read more then Constants.READ_TRSHOLD times, or if MAX_READ_TRYS has been reached
		 */
		public boolean add(byte val){
			attempts[attemptN++] = val;
			return ++vals[val] >= Constants.READ_TRESHOLD || attemptN >= attempts.length;
		}
		
		/**
		 * returns the value that is read most, and should thus be considered the read value
		 * @return the most read value
		 */
		public byte value(){
			int maxReadCount = vals[attempts[0]];
			byte maxReadValue = attempts[0];
			for(int i=1; i<attempts.length; i++)
				if(maxReadCount < vals[attempts[i]]){
					maxReadValue = attempts[i];
					maxReadCount = vals[attempts[i]];
				}
			return maxReadValue;
		}
		
		/**
		 * Call this method to reset the value register (effectivly empty it)
		 */
		public void reset(){
			for(int i=0; i<attempts.length; i++)
				vals[attempts[i]] = 0;
			attemptN = 0;
		}
	}
}
